package org.fast.framework.helper;

import org.fast.framework.annotation.Aspect;
import org.fast.framework.annotation.Service;
import org.fast.framework.container.BeanContainer;
import org.fast.framework.container.ClassContainer;
import org.fast.framework.proxy.AspectProxy;
import org.fast.framework.proxy.Proxy;
import org.fast.framework.proxy.ProxyManager;
import org.fast.framework.proxy.TransactionProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.util.*;

/**
 * 切面助手类
 */
public final class AopHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(AopHelper.class);

    static {
        try {
            Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
            Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
            for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
                Class<?> targetClass = targetEntry.getKey();
                List<Proxy> proxyList = targetEntry.getValue();
                Object proxy = ProxyManager.createProxy(targetClass, proxyList);
                BeanContainer.setBean(targetClass, proxy);
            }
        } catch (Exception e) {
            LOGGER.error("aop failure", e);
        }
    }

    /**
     * 创建代理类与目标类的映射关系
     *
     * @return
     * @throws Exception
     */
    private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
        Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap();
        // 获取代理类集合，代理类必须是AspectProxy的子类
        Set<Class<?>> proxyClassSet = ClassContainer.getClassSetBySuper(AspectProxy.class);
        for (Class<?> proxyClass : proxyClassSet) {
            // 代理类必须带有@Aspect注解
            if (proxyClass.isAnnotationPresent(Aspect.class)) {
                Aspect aspect = proxyClass.getAnnotation(Aspect.class);
                // 获取代理类所代理的注解
                Class<? extends Annotation> annotation = aspect.value();
                if (annotation != null && !annotation.equals(Aspect.class)) {
                    Set<Class<?>> targetClassSet = ClassContainer.getClassSetByAnnotation(annotation);
                    proxyMap.put(proxyClass, targetClassSet);
                }
            }
        }
        // 加入事务代理
        Set<Class<?>> serviceClassSet = ClassContainer.getClassSetByAnnotation(Service.class);
        proxyMap.put(TransactionProxy.class, serviceClassSet);
        return proxyMap;
    }

    /**
     * 创建目标类与代理对象数组的映射关系
     *
     * @param proxyMap
     * @return
     * @throws Exception
     */
    private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
        Map<Class<?>, List<Proxy>> targetMap = new HashMap();
        for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()) {
            Class<?> proxyClass = proxyEntry.getKey();
            Set<Class<?>> targetClassSet = proxyEntry.getValue();
            for (Class<?> targetClass : targetClassSet) {
                Proxy proxy = (Proxy) proxyClass.newInstance();
                List<Proxy> proxyList = targetMap.get(targetClass);
                if (proxyList == null) {
                    proxyList = new ArrayList();
                    proxyList.add(proxy);
                    targetMap.put(targetClass, proxyList);
                } else {
                    proxyList.add(proxy);
                }
            }
        }
        return targetMap;
    }
}
